package com.borya.service.mobile.impl;

import java.io.*;
import java.util.Objects;

import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSONObject;
import com.borya.framework.annotation.Autowired;
import com.borya.framework.annotation.Component;
import com.borya.framework.core.ServerRequest;
import com.borya.framework.util.ObjectUtils;
import com.borya.model.db.User;
import com.borya.service.mobile.MerchantService;
import com.borya.service.mobile.UploadImgFileService;
import com.borya.service.mobile.UserService;
import com.borya.statuscode.StatusCode;
import com.borya.util.md5.MD5Util;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;

@Component("uploadImgFileService")
public class UploadImgFileServiceImpl implements UploadImgFileService {

	private Logger log = Logger.getLogger(getClass());
	@Autowired("userServiceImpl")
	private UserService userService;
	@Autowired("merchantServiceImpl")
	private MerchantService merchantService;

	@Override
	public String upload(User user, ServerRequest request, JSONObject params) {
		try {
			File file = request.fileUploads().get(0).getFile();
			log.info("文件流上传，文件名为：" + file.getName());
			// 判断图片一致性，MD5
			String reqMd5 = params.getString("md5");

			// checkType:"1/2", // 1 默认文件流,2
			// 文件流字节拼接MD5(二进制转string去除逗号,MD5小写(32位))
			if (params.containsKey("checkType")) {
				if (Objects.equals(params.getIntValue("checkType"), 2)) {
					if (checkFileMD5FromSDK(file, reqMd5)) {
						log.warn("图片md5不一致,可能被攻击," + params);
						return StatusCode.PARAM_ERROR.toJSON("请求网络异常,请联系客服");
					}
				} else if (Objects.equals(params.getIntValue("checkType"), 1)) {
					String fileMD5 = MD5Util.getFileMD5(file);
					// 兼容 卡盟app老接口
					if (!fileMD5.equals(reqMd5)) {
						log.warn("图片md5不一致,可能被攻击," + params);
						return StatusCode.PARAM_ERROR.toJSON("请求网络异常,请联系客服");
					}
				} else {
					log.warn("请求类型错误,可能被攻击," + params);
					return StatusCode.PARAM_ERROR.toJSON("请求网络异常,请联系客服");
				}
			} else {
				String fileMD5 = MD5Util.getFileMD5(file);
				// 兼容 卡盟app老接口
				if (!fileMD5.equals(reqMd5)) {
					log.warn("图片md5不一致,可能被攻击," + params);
					return StatusCode.PARAM_ERROR.toJSON("请求网络异常,请联系客服");
				}
			}
			//String img = tansformFileToBase64(file);
            final String uploadType = params.getString("uploadType");
			if (ObjectUtils.isNullOrEmpty(uploadType)) {
				// 参数错误，缺少uploadType
				return StatusCode.PARAM_ERROR.toJSON("参数错误，缺少uploadType");
			}
			if ("1".equals(uploadType) || "3".equals(uploadType)) {
				// c/user/uploadImg
				String result = userService.uploadImg(user, params,file);
				params.put("img", "");
				log.info("OUT[" + result + "]");
				return result;
			} else if ("2".equals(uploadType)) {
				// ums/c/merchant/shqpSign
				String r = merchantService.setImg(user, params, 1);
				params.put("img", "");
				log.info("get return : " + r);
				return r;
			} else {
				return StatusCode.PARAM_ERROR.toJSON("参数错误，缺少uploadType");
			}
		} catch (IOException e) {
			log.error(e.getMessage(), e);
			return StatusCode.SYSTEM_EXCEPTION.toJSON();
		} finally {
			System.gc();
		}
	}

    private byte[] tansformFileToByteArray(File file) {
        try {
            FileInputStream fis = new FileInputStream(file);

            //新的 byte 数组输出流，缓冲区容量1024byte
            ByteArrayOutputStream bos = new ByteArrayOutputStream(1024);
            //缓存
            byte[] b = new byte[1024];
            int n;
            while ((n = fis.read(b)) != -1) {
                bos.write(b, 0, n);
            }
            fis.close();
            //改变为byte[]
            byte[] data = bos.toByteArray();
            //
            bos.close();
            return data;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    private String tansformFileToBase64(File file) {
		if (file == null) {
			return null;
		}
		String base64 = null;
		FileInputStream fin = null;
		try {
			fin = new FileInputStream(file);
			byte[] buff = new byte[fin.available()];
			fin.read(buff);
			base64 = Base64.encode(buff);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (fin != null) {
				try {
					fin.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return base64;
	}

	/**
	 * web上图片上传,md5不一样的文件校验方式
	 * 
	 * @param file
	 * @return true 校验通过,false 校验失败
	 */
	private boolean checkFileMD5FromSDK(File file, String reqMd5) {
		try (FileInputStream fis = new FileInputStream(file);) {
			// File file = request.fileUploads().get(0).getFile();
			log.info("文件流上传，文件名为：" + file.getName());
			byte[] buffer = new byte[(int) file.length()];
			int offset = 0;
			int numRead = 0;
			while (offset < buffer.length && (numRead = fis.read(buffer, offset, buffer.length - offset)) >= 0) {
				offset += numRead;
			}
			// 确保所有数据均被读取
			if (offset != buffer.length) {
				// throw new IOException("Could not completely read file " +
				// file.getName());
				return false;
			}

			StringBuilder stringBuilder = new StringBuilder(512);
			for (byte by : buffer) {
				stringBuilder.append((int) by);
			}

			String md5Str = MD5Util.getMD5(stringBuilder.toString());
			return Objects.equals(md5Str, reqMd5);
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}
}
